package org.abc.fund.controller.factorController;

import lombok.RequiredArgsConstructor;
import org.abc.fund.entity.factorEntity.Factor;
import org.abc.fund.service.factorService.FactorService;
import org.abc.fund.service.factorService.PythonScriptService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Python脚本管理控制器
 */
@RestController
@RequestMapping("/script")

@CrossOrigin(originPatterns = "*", maxAge = 3600)
@RequiredArgsConstructor
public class ScriptController {

    private static final Logger log = LoggerFactory.getLogger(ScriptController.class);

    private final PythonScriptService pythonScriptService;
    private final FactorService factorService;

    // 脚本存储目录
    private static final String SCRIPT_DIR = "scripts";

    /**
     * 获取脚本列表
     */
    @GetMapping("/getScriptList")
    public ResponseEntity<List<Map<String, Object>>> getScripts() {
        try {
            Path scriptPath = Paths.get(SCRIPT_DIR);
            if (!Files.exists(scriptPath)) {
                Files.createDirectories(scriptPath);
                return ResponseEntity.ok(new ArrayList<>());
            }

            List<Map<String, Object>> scripts = Files.list(scriptPath)
                    .filter(path -> path.toString().endsWith(".py"))
                    .map(path -> {
                        Map<String, Object> script = new HashMap<>();
                        script.put("id", path.getFileName().toString());
                        script.put("name", path.getFileName().toString().replace(".py", ""));
                        try {
                            script.put("size", Files.size(path));
                            script.put("uploadTime", Files.getLastModifiedTime(path).toString());
                            script.put("content", Files.readString(path));
                        } catch (IOException e) {
                            script.put("size", 0L);
                            script.put("uploadTime", "");
                            script.put("content", "");
                        }
                        return script;
                    })
                    .collect(Collectors.toList());

            return ResponseEntity.ok(scripts);
        } catch (IOException e) {
            log.error("获取脚本列表失败", e);
            return ResponseEntity.badRequest().build();
        }
    }

    /**
     * 上传脚本文件
     */
    @PostMapping("/script/upload")
    public ResponseEntity<Map<String, Object>> uploadScriptFile(@RequestParam("file") MultipartFile file) {
        try {
            if (file.isEmpty()) {
                return ResponseEntity.badRequest().body(Map.of("message", "文件不能为空"));
            }

            String originalFilename = file.getOriginalFilename();
            if (originalFilename == null || !originalFilename.endsWith(".py")) {
                return ResponseEntity.badRequest().body(Map.of("message", "只能上传Python文件(.py)"));
            }

            Path scriptPath = Paths.get(SCRIPT_DIR);
            if (!Files.exists(scriptPath)) {
                Files.createDirectories(scriptPath);
            }

            Path filePath = scriptPath.resolve(originalFilename);
            Files.write(filePath, file.getBytes());

            Map<String, Object> result = Map.of(
                    "message", "脚本文件上传成功",
                    "fileName", originalFilename,
                    "uploadTime", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            );
            return ResponseEntity.ok(result);
        } catch (IOException e) {
            log.error("脚本文件上传失败", e);
            return ResponseEntity.badRequest().body(Map.of("message", "脚本文件上传失败: " + e.getMessage()));
        }
    }

    /**
     * 创建或更新脚本（通过代码编辑器）
     */
    @PostMapping
    public ResponseEntity<Map<String, Object>> createOrUpdateScript(@RequestBody Map<String, String> scriptData) {
        try {
            String name = scriptData.get("name");
            String content = scriptData.get("content");
            String description = scriptData.get("description");

            if (name == null || content == null) {
                return ResponseEntity.badRequest().body(Map.of("message", "脚本名称和内容不能为空"));
            }

            if (!name.endsWith(".py")) {
                name = name + ".py";
            }

            Path scriptPath = Paths.get(SCRIPT_DIR);
            if (!Files.exists(scriptPath)) {
                Files.createDirectories(scriptPath);
            }

            Path filePath = scriptPath.resolve(name);
            Files.writeString(filePath, content);

            Map<String, Object> result = Map.of(
                    "message", "脚本保存成功",
                    "fileName", name,
                    "uploadTime", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            );
            return ResponseEntity.ok(result);
        } catch (IOException e) {
            log.error("脚本保存失败", e);
            return ResponseEntity.badRequest().body(Map.of("message", "脚本保存失败: " + e.getMessage()));
        }
    }

    /**
     * 删除脚本
     */
    @DeleteMapping("/deleteScript/{scriptId}")
    public ResponseEntity<Map<String, Object>> deleteScript(@PathVariable String scriptId) {
        try {
            Path scriptPath = Paths.get(SCRIPT_DIR, scriptId);
            if (Files.exists(scriptPath)) {
                Files.delete(scriptPath);
                return ResponseEntity.ok(Map.of("message", "脚本删除成功"));
            } else {
                return ResponseEntity.notFound().build();
            }
        } catch (IOException e) {
            log.error("脚本删除失败", e);
            return ResponseEntity.badRequest().body(Map.of("message", "脚本删除失败: " + e.getMessage()));
        }
    }

    /**
     * 执行脚本
     */
    @PostMapping("/{scriptId}/execute")
    public ResponseEntity<Map<String, Object>> executeScript(@PathVariable String scriptId,
                                                             @RequestBody(required = false) Map<String, Object> parameters) {
        try {
            Path scriptPath = Paths.get(SCRIPT_DIR, scriptId);
            if (!Files.exists(scriptPath)) {
                return ResponseEntity.notFound().build();
            }

            String scriptContent = Files.readString(scriptPath);
            Map<String, Object> executionResult = pythonScriptService.executeScript(scriptContent);

            Map<String, Object> result = new HashMap<>();
            result.put("scriptId", scriptId);
            result.put("success", executionResult.get("success"));
            result.put("message", executionResult.get("message"));
            result.put("output", executionResult.get("output"));
            result.put("data", executionResult.get("data"));
            result.put("executionTime", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));

            return ResponseEntity.ok(result);
        } catch (Exception e) {
            log.error("脚本执行失败", e);
            Map<String, Object> result = Map.of(
                    "scriptId", scriptId,
                    "success", false,
                    "message", "脚本执行失败: " + e.getMessage(),
                    "executionTime", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            );
            return ResponseEntity.badRequest().body(result);
        }
    }

    /**
     * 获取脚本内容
     */
    @GetMapping("/{scriptId}/content")
    public ResponseEntity<Map<String, Object>> getScriptContent(@PathVariable String scriptId) {
        try {
            Path scriptPath = Paths.get(SCRIPT_DIR, scriptId);
            if (!Files.exists(scriptPath)) {
                return ResponseEntity.notFound().build();
            }

            String content = Files.readString(scriptPath);
            Map<String, Object> result = Map.of(
                    "scriptId", scriptId,
                    "content", content,
                    "size", Files.size(scriptPath),
                    "lastModified", Files.getLastModifiedTime(scriptPath).toString()
            );

            return ResponseEntity.ok(result);
        } catch (IOException e) {
            log.error("获取脚本内容失败", e);
            return ResponseEntity.badRequest().body(Map.of("message", "获取脚本内容失败: " + e.getMessage()));
        }
    }

    /**
     * 获取脚本模板
     */
    @GetMapping("/templates")
    public ResponseEntity<Map<String, String>> getScriptTemplates() {
        Map<String, String> templates = new HashMap<>();

        // 基础数据获取模板
        templates.put("basic_data_fetch",
                "import pandas as pd\n" +
                        "import numpy as np\n" +
                        "import json\n" +
                        "import sys\n" +
                        "from datetime import datetime\n\n" +
                        "# 基础数据获取脚本模板\n" +
                        "def fetch_data():\n" +
                        "    \"\"\"获取基础数据\"\"\"\n" +
                        "    # 这里添加你的数据获取逻辑\n" +
                        "    data = {\n" +
                        "        'fund_code': '000001',\n" +
                        "        'date': '2024-01-01',\n" +
                        "        'value': 1.2345\n" +
                        "    }\n" +
                        "    return data\n\n" +
                        "if __name__ == '__main__':\n" +
                        "    try:\n" +
                        "        result = fetch_data()\n" +
                        "        print(json.dumps(result))\n" +
                        "    except Exception as e:\n" +
                        "        print(f'ERROR: {str(e)}')\n" +
                        "        sys.exit(1)\n"
        );

        // 因子计算模板
        templates.put("factor_calculation",
                "import pandas as pd\n" +
                        "import numpy as np\n" +
                        "import json\n" +
                        "import sys\n" +
                        "from datetime import datetime\n\n" +
                        "# 因子计算脚本模板\n" +
                        "def calculate_factor(data):\n" +
                        "    \"\"\"计算因子值\"\"\"\n" +
                        "    # 这里添加你的因子计算逻辑\n" +
                        "    factor_value = np.mean(data['values']) if 'values' in data else 0.0\n" +
                        "    return factor_value\n\n" +
                        "if __name__ == '__main__':\n" +
                        "    try:\n" +
                        "        # 模拟输入数据\n" +
                        "        input_data = {\n" +
                        "            'values': [1.1, 1.2, 1.3, 1.4, 1.5]\n" +
                        "        }\n" +
                        "        result = calculate_factor(input_data)\n" +
                        "        output = {\n" +
                        "            'factor_value': result,\n" +
                        "            'calculation_time': datetime.now().isoformat()\n" +
                        "        }\n" +
                        "        print(json.dumps(output))\n" +
                        "    except Exception as e:\n" +
                        "        print(f'ERROR: {str(e)}')\n" +
                        "        sys.exit(1)\n"
        );

        // 网络数据获取模板
        templates.put("web_data_fetch",
                "import requests\n" +
                        "import json\n" +
                        "import sys\n" +
                        "from datetime import datetime\n\n" +
                        "# 网络数据获取脚本模板\n" +
                        "def fetch_web_data(url):\n" +
                        "    \"\"\"从网络获取数据\"\"\"\n" +
                        "    try:\n" +
                        "        response = requests.get(url, timeout=10)\n" +
                        "        response.raise_for_status()\n" +
                        "        return response.json()\n" +
                        "    except Exception as e:\n" +
                        "        return {'error': str(e)}\n\n" +
                        "if __name__ == '__main__':\n" +
                        "    try:\n" +
                        "        # 示例URL，请替换为实际的数据源\n" +
                        "        url = 'https://api.example.com/data'\n" +
                        "        result = fetch_web_data(url)\n" +
                        "        print(json.dumps(result))\n" +
                        "    except Exception as e:\n" +
                        "        print(f'ERROR: {str(e)}')\n" +
                        "        sys.exit(1)\n"
        );

        // 数据处理模板
        templates.put("data_processing",
                "import pandas as pd\n" +
                        "import numpy as np\n" +
                        "import json\n" +
                        "import sys\n" +
                        "from datetime import datetime\n\n" +
                        "# 数据处理脚本模板\n" +
                        "def process_data(data_list):\n" +
                        "    \"\"\"处理数据列表\"\"\"\n" +
                        "    if not data_list:\n" +
                        "        return {'error': '数据列表为空'}\n" +
                        "    \n" +
                        "    # 转换为DataFrame进行处理\n" +
                        "    df = pd.DataFrame(data_list)\n" +
                        "    \n" +
                        "    # 计算统计信息\n" +
                        "    stats = {\n" +
                        "        'count': len(df),\n" +
                        "        'mean': df['value'].mean() if 'value' in df.columns else 0,\n" +
                        "        'std': df['value'].std() if 'value' in df.columns else 0,\n" +
                        "        'min': df['value'].min() if 'value' in df.columns else 0,\n" +
                        "        'max': df['value'].max() if 'value' in df.columns else 0\n" +
                        "    }\n" +
                        "    \n" +
                        "    return stats\n\n" +
                        "if __name__ == '__main__':\n" +
                        "    try:\n" +
                        "        # 模拟输入数据\n" +
                        "        input_data = [\n" +
                        "            {'id': 1, 'value': 1.1},\n" +
                        "            {'id': 2, 'value': 1.2},\n" +
                        "            {'id': 3, 'value': 1.3}\n" +
                        "        ]\n" +
                        "        result = process_data(input_data)\n" +
                        "        print(json.dumps(result))\n" +
                        "    except Exception as e:\n" +
                        "        print(f'ERROR: {str(e)}')\n" +
                        "        sys.exit(1)\n"
        );

        return ResponseEntity.ok(templates);
    }

    /**
     * 直接执行Python代码（不保存文件）
     */
    @PostMapping("/api/python/execute-code")
    public ResponseEntity<Map<String, Object>> executeCode(@RequestBody Map<String, Object> request) {
        try {
            String code = (String) request.get("code");
            if (code == null || code.trim().isEmpty()) {
                return ResponseEntity.badRequest().body(Map.of("success", false, "message", "代码内容不能为空"));
            }
            // 执行Python代码，捕获stdout
            Map<String, Object> executionResult = pythonScriptService.executeScript(code);
            String output = (String) executionResult.get("output");
            // 校验输出为JSON数组且字段齐全
            List<String> requiredFields = List.of("factorCode", "factorName", "factorType", "fundCode", "value");
            List<Map<String, Object>> dataList;
            try {
                dataList = new com.fasterxml.jackson.databind.ObjectMapper().readValue(output, List.class);
            } catch (Exception e) {
                return ResponseEntity.ok(Map.of("success", false, "message", "Python输出不是有效的JSON数组"));
            }
            for (Map<String, Object> item : dataList) {
                for (String field : requiredFields) {
                    if (!item.containsKey(field)) {
                        return ResponseEntity.ok(Map.of("success", false, "message", "缺少字段: " + field));
                    }
                }
            }
            // 批量插入factors表
            for (Map<String, Object> item : dataList) {
                Factor factor = new Factor();
                factor.setFactorCode((String) item.get("factorCode"));
                factor.setFactorName((String) item.get("factorName"));
                factor.setFactorType((String) item.get("factorType"));
                factor.setFundCode((String) item.get("fundCode"));
                factor.setValue(Double.parseDouble(item.get("value").toString()));
                factor.setEnabled(true);
                factor.setDescription(item.getOrDefault("description", "").toString());
                factor.setCreatedBy("python-script");
                factor.setUpdatedBy("python-script");
                factorService.createFactor(factor);
            }
            return ResponseEntity.ok(Map.of("success", true, "message", "接入成功"));
        } catch (Exception e) {
            return ResponseEntity.ok(Map.of("success", false, "message", "执行或入库失败: " + e.getMessage()));
        }
    }
}